package main

import (
	"bufio"
	"fmt"
	"log"
	"math/rand"
	"net"
	"strconv"
	"sync"
	"time"
)

// 定义用户组
type User struct {
	ID             uint
	Name           string
	Addr           string
	LoginAt        time.Time
	MessageChannel chan string
}

// 定义行为信息通道
var (
	// 进入通道信息
	loginChannel = make(chan *User)
	// 离开通道信息
	logoutChannel = make(chan *User)
	// 信息通道
	messageChannel = make(chan string, 8)
)

func (u User) Info() string {
	return u.Addr +", UID:"+ strconv.Itoa(int(u.ID)) +", 用户名:" + u.Name + ", 登陆时间:" + u.LoginAt.Format("2006-01-02 15:04:05")
}

// 用户ID设置
var firstName = []string{
	"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施",
	"张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范",
	"彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷",
	"贺", "倪",
}
var lastName = []string{
	"伟", "刚", "勇", "毅", "俊", "峰", "强", "军", "平", "保", "东", "文", "辉", "力", "明", "永", "健", "世", "广", "志", "义",
	"兴", "良", "海", "山", "仁", "波", "宁", "贵", "福", "生", "龙", "元", "全", "国", "胜", "学", "祥", "才", "发", "武", "新",
	"利", "清", "飞", "彬", "富", "顺", "信", "子", "杰", "涛", "昌", "成", "康", "星",
}

func SetName() string {
	rand.Seed(time.Now().Unix())
	var last string
	n := rand.Intn(2)
	for i := 0; i <= n; i++ {
		last += fmt.Sprint(lastName[rand.Intn(len(lastName)-1)])
	}
	
	return fmt.Sprintf("%s%s", fmt.Sprint(firstName[rand.Intn(len(firstName)-1)]), last)
}

// 发送信息
func sendMessage(conn net.Conn, ch <-chan string) {
	for msg := range ch {
		_, _ = fmt.Fprintln(conn, msg)
	}
}

var(
	userID uint
	locker sync.RWMutex
)

// 用户ID设置
func SetID() uint {
	
	locker.RLock()
	defer locker.RUnlock()
	userID ++
	return userID
	
}

// 信息处理函数
func handleConn(conn net.Conn) {
	defer conn.Close()
	
	// 定义用户实例
	var user User
	user.ID = SetID()
	user.Name = SetName()
	user.Addr = conn.RemoteAddr().String()
	user.LoginAt = time.Now()
	user.MessageChannel = make(chan string, 8)
	
	// 发送信息
	go sendMessage(conn, user.MessageChannel)
	
	// 传递广播
	user.MessageChannel <- "欢迎:" + user.Info()
	messageChannel <- "用户:`" + user.Name + "` 进来了"
	
	loginChannel <- &user
	
	// 超时用户处理
	var userActive = make(chan struct{})
	go func() {
		d := 5 * time.Minute
		timer := time.NewTimer(d)
		for {
			select {
			case <-timer.C:
				conn.Close()
			case <-userActive:
				timer.Reset(d)
			}
		}
	}()
	
	// 监听控制台
	userActive <- struct{}{}
	input := bufio.NewScanner(conn)
	for input.Scan() {
		messageChannel <- "用户" + user.Name + "说:" + input.Text()
	}
	
	if err := input.Err(); err != nil {
		log.Println("信息读取错误:", err)
	}
	
	logoutChannel <- &user
	messageChannel <- "用户:`" + user.Name + "` 离开了"
}

// 广播
func broadCaster() {
	users := make(map[*User]struct{})
	
	for {
		select {
		case user := <-loginChannel:
			users[user] = struct{}{}
		case user := <-logoutChannel:
			delete(users, user)
			close(user.MessageChannel)
		case msg := <-messageChannel:
			for user := range users {
				user.MessageChannel <- msg
			}
		}
	}
}

func main() {
	listener, err := net.Listen("tcp", "127.0.0.1:3000")
	if err != nil {
		panic(err)
		return
	} else {
		fmt.Println("sever running at ->", listener.Addr().String())
	}
	go broadCaster()
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		go handleConn(conn)
	}
}
